package com.yzh.luckydraw.domain.rule.service.engine;

import com.yzh.luckydraw.common.Constants;
import com.yzh.luckydraw.domain.rule.model.aggregates.TreeRuleRich;
import com.yzh.luckydraw.domain.rule.model.req.DecisionMatterReq;
import com.yzh.luckydraw.domain.rule.model.res.EngineResult;
import com.yzh.luckydraw.domain.rule.model.vo.TreeNodeVO;
import com.yzh.luckydraw.domain.rule.model.vo.TreeRootVO;
import com.yzh.luckydraw.domain.rule.service.logic.LogicFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * 规则引擎基础类
 */
public abstract class EngineBase extends EngineConfig implements EngineFilter {
    private Logger logger = LoggerFactory.getLogger(EngineBase.class);

    /**
     * 这里由子类实现具体逻辑
     * @param req
     * @return
     */
    @Override
    public EngineResult process(DecisionMatterReq req) {
        throw new RuntimeException("未实现规则引擎服务");
    }

    /**
     * 执行规则过滤，拿到符合用户的活动策略
     * @param treeRuleRich 规则树聚合对象，包含树根信息、树链路信息
     * @param req          用户请求参数，包含树id、用户id、决策值
     * @return             返回叶子节点的详情信息（包含活动Id）
     */
    protected TreeNodeVO engineDecisionMaker(TreeRuleRich treeRuleRich, DecisionMatterReq req) {
        //获取树根信息和节点链路
        TreeRootVO treeRoot = treeRuleRich.getTreeRoot();
        Map<Long, TreeNodeVO> treeNodeMap = treeRuleRich.getTreeNodeMap();
        //获得树根节点Id并根据id获得该节点信息
        Long treeRootNodeId = treeRoot.getTreeRootNodeId();
        TreeNodeVO treeNodeVO = treeNodeMap.get(treeRootNodeId);

        //找到叶子节点(果实)
        while (Constants.NodeType.STEM.equals(treeNodeVO.getNodeType())) {
            //获得规则key(userAge/userGender)
            String ruleKey = treeNodeVO.getRuleKey();
            //根据规则key获得相应的决策过滤器对象
            LogicFilter logicFilter = logicFilterMap.get(ruleKey);
            //执行逻辑过滤器
            String matterValue = logicFilter.matterValue(req);
            Long nextId = logicFilter.filter(matterValue, treeNodeVO.getTreeNodeLineInfoList());
            //遍历到下一个节点，赋值给treeNodeVO
            treeNodeVO = treeNodeMap.get(nextId);
            logger.info("决策树引擎=>{} userId：{} treeId：{} treeNode：{} ruleKey：{} matterValue：{}", treeRoot.getTreeName(), req.getUserId(), req.getTreeId(), treeNodeVO.getTreeNodeId(), ruleKey, matterValue);

        }
        return treeNodeVO;
    }
}
